#include <linux/init.h> /* Needed for the macros */
#include <linux/kernel.h> /* Needed for pr_info() */
#include <linux/module.h> /* Needed by all modules */
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/regmap.h>


#define BMP280_REG_TEMP_XLSB		0xFC
#define BMP280_REG_TEMP_LSB		0xFB
#define BMP280_REG_TEMP_MSB		0xFA
#define BMP280_REG_PRESS_XLSB		0xF9
#define BMP280_REG_PRESS_LSB		0xF8
#define BMP280_REG_PRESS_MSB		0xF7

#define BMP280_REG_CONFIG		0xF5
#define BMP280_REG_CTRL_MEAS		0xF4
#define BMP280_REG_STATUS		0xF3
#define BMP280_REG_RESET		0xE0
#define BMP280_REG_ID			0xD0

#define BMP280_REG_COMP_TEMP_START	0x88
#define BMP280_COMP_TEMP_REG_COUNT	6

#define BMP280_REG_COMP_PRESS_START	0x8E
#define BMP280_COMP_PRESS_REG_COUNT	18

#define BMP280_FILTER_MASK		(BIT(4) | BIT(3) | BIT(2))
#define BMP280_FILTER_OFF		0
#define BMP280_FILTER_2X		BIT(2)
#define BMP280_FILTER_4X		BIT(3)
#define BMP280_FILTER_8X		(BIT(3) | BIT(2))
#define BMP280_FILTER_16X		BIT(4)

#define BMP280_OSRS_TEMP_MASK		(BIT(7) | BIT(6) | BIT(5))
#define BMP280_OSRS_TEMP_SKIP		0
#define BMP280_OSRS_TEMP_1X		BIT(5)
#define BMP280_OSRS_TEMP_2X		BIT(6)
#define BMP280_OSRS_TEMP_4X		(BIT(6) | BIT(5))
#define BMP280_OSRS_TEMP_8X		BIT(7)
#define BMP280_OSRS_TEMP_16X		(BIT(7) | BIT(5))

#define BMP280_OSRS_PRESS_MASK		(BIT(4) | BIT(3) | BIT(2))
#define BMP280_OSRS_PRESS_SKIP		0
#define BMP280_OSRS_PRESS_1X		BIT(2)
#define BMP280_OSRS_PRESS_2X		BIT(3)
#define BMP280_OSRS_PRESS_4X		(BIT(3) | BIT(2))
#define BMP280_OSRS_PRESS_8X		BIT(4)
#define BMP280_OSRS_PRESS_16X		(BIT(4) | BIT(2))

#define BMP280_MODE_MASK		(BIT(1) | BIT(0))
#define BMP280_MODE_SLEEP		0
#define BMP280_MODE_FORCED		BIT(0)
#define BMP280_MODE_NORMAL		(BIT(1) | BIT(0))

#define BMP280_CHIP_ID			0x58
#define BMP280_SOFT_RESET_VAL		0xB6
/**
 *




 https://www.linuxjournal.com/search/node?keys=input+subsystem



 There are two ways for a user space application to interact with an IIO driver.

 /sys/bus/iio/iio:deviceX/, this represents a hardware sensor and groups together the data channels of the same chip.
 /dev/iio:deviceX, character device node interface used for buffered data transfer and for events information retrieval.




 Available standard attributes for IIO devices are described in the Documentation/ABI/testing/sysfs-bus-iio file in the Linux kernel sources.

 https://bootlin.com/blog/the-backbone-of-a-linux-industrial-i-o-driver/

 https://www.kernel.org/doc/html/v4.12/driver-api/iio/intro.html


 There are two ways for a user space application to interact with an IIO driver.

 /sys/bus/iio/iio:deviceX/, this represents a hardware sensor and groups together the data channels of the same chip.
 /dev/iio:deviceX, character device node interface used for buffered data transfer and for events information retrieval.


 /sys/bus/iio/devices/iio:device2
  *
  *
  * https://pandysong.github.io/blog/post/regmap/


 */

struct iio_dev *myiio;

struct bmp280_data {
	struct i2c_client *client;
	struct mutex lock;
	struct regmap *regmap;
	s32 t_fine;
};


/**
 * function to request a value from the device. mask specifies which value. Note 0 means a reading of the channel in question.
 * Return value will specify the type of value returned by the device. val and val2 will contain the elements making up the returned value.
 *
 *
 */


static int bmp280_read_temp(struct bmp280_data *data,
			    int *val)
{
	int ret;
	__be32 tmp = 0;
	s32 adc_temp, comp_temp;

	ret = regmap_bulk_read(data->regmap, BMP280_REG_TEMP_MSB,
			       (u8 *) &tmp, 3);
	if (ret < 0) {
		dev_err(&data->client->dev, "failed to read temperature\n");
		return ret;
	}

	adc_temp = be32_to_cpu(tmp) >> 12;
//	comp_temp = bmp280_compensate_temp(data, adc_temp);

	/*
	 * val might be NULL if we're called by the read_press routine,
	 * who only cares about the carry over t_fine value.
	 */
	if (val) {
		*val = comp_temp * 10;
		return IIO_VAL_INT;
	}

	return 0;
}


static int bmp280_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *chan,
			   int *val, int *val2, long mask)
{
	int ret;
	struct bmp280_data *data = iio_priv(indio_dev);

	mutex_lock(&data->lock);

	switch (mask) {
	case IIO_CHAN_INFO_PROCESSED:
		switch (chan->type) {
		case IIO_PRESSURE:
//			ret = bmp280_read_press(data, val, val2);
			break;
		case IIO_TEMP:
			ret = bmp280_read_temp(data, val);
			break;
		default:
			ret = -EINVAL;
			break;
		}
		break;
	default:
		ret = -EINVAL;
		break;
	}
	mutex_unlock(&data->lock);
	return ret;
}




static const struct iio_chan_spec bmp280_channels[] = {
	{
		.type = IIO_PRESSURE,
		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
	},
	{
		.type = IIO_TEMP,
		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
	},
};

static const struct iio_info info = { .driver_module = THIS_MODULE, .read_raw =
		bmp280_read_raw, };


static const struct regmap_config my_regmap_config = {
	.reg_bits = 8,
	.val_bits = 8,
//	.max_register = BMP280_REG_TEMP_XLSB,
	.cache_type = REGCACHE_RBTREE,
//	.writeable_reg = bmp280_is_writeable_reg,
//	.volatile_reg = bmp280_is_volatile_reg,
};

static int bmp280_chip_init(struct bmp280_data *data)
{
	int ret;

	ret = regmap_update_bits(data->regmap, BMP280_REG_CTRL_MEAS,
				 BMP280_OSRS_TEMP_MASK |
				 BMP280_OSRS_PRESS_MASK |
				 BMP280_MODE_MASK,
				 BMP280_OSRS_TEMP_2X |
				 BMP280_OSRS_PRESS_16X |
				 BMP280_MODE_NORMAL);

				 pr_err("bmp280_probe bmp280_chip_init\n");
	if (ret < 0) {
		dev_err(&data->client->dev,
			"failed to write ctrl_meas register\n");
		return ret;
	}

	ret = regmap_update_bits(data->regmap, BMP280_REG_CONFIG,
				 BMP280_FILTER_MASK,
				 BMP280_FILTER_4X);
	if (ret < 0) {
		dev_err(&data->client->dev,
			"failed to write config register\n");
		return ret;
	}

	return ret;
}




int myprobe(struct i2c_client *client, const struct i2c_device_id *id) {
	unsigned int chip_id;
	int ret;
	unsigned int read1;
	struct bmp280_data *data;
	int  sd ;
	pr_info("bmp280 probe\n");
	pr_err("name: = %s \n", client->name);
	pr_err("name: = 0x%x  \n", client->addr);
	pr_err("i2c_device_id: = %s  \n", id->name);

	myiio = devm_iio_device_alloc(&client->dev, sizeof(*myiio));
	myiio->channels = bmp280_channels;
	myiio->num_channels = ARRAY_SIZE(bmp280_channels);
	myiio->name = "myiio1025";
	myiio->dev.parent = &client->dev;
	myiio->info = &info;
	myiio->modes = INDIO_DIRECT_MODE;

	data = iio_priv(myiio);
	mutex_init(&data->lock);
		data->client = client;
	data->regmap = devm_regmap_init_i2c(client, &my_regmap_config);
	ret = regmap_read(data->regmap, BMP280_REG_ID, &chip_id);
//	pr_err("chip_id 0x%x \n", chip_id);  //  0x58


//	pr_err("BIT(3) = %lu \n", BIT(sd3));
//	pr_err("BIT(0) = %lu \n", BIT(0));

	bmp280_chip_init(data);

	ret = regmap_update_bits(data->regmap, BMP280_REG_CTRL_MEAS,0xff,0x00);

//	ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,0xff,0xf);


//	  sd= BIT(1) |  BIT(2) |  BIT(3) | BIT(4) |  BIT(5) |  BIT(6) |  BIT(7) ;
	  sd= BIT(1) ;
//	ret = regmap_update_bits(data->regmap, BMP280_REG_CTRL_MEAS,sd,sd);
//	regmap_write(data->regmap, BMP280_REG_CTRL_MEAS,10);
	regmap_read(data->regmap,BMP280_REG_CTRL_MEAS,&read1);

//	pr_err("sd 0x%x \n", sd);
//
//	pr_err("sd %d \n", sd);




	pr_err("read1 0x%x \n", read1);   // 0x57

	pr_err("read1 %d \n", read1);   // 0x57



	return devm_iio_device_register(&client->dev, myiio);
}

int myremove(struct i2c_client *client) {
	pr_info("remove\n");
	devm_iio_device_unregister(&client->dev, myiio);
	iio_device_free(myiio);
	return 0;
}

static const struct i2c_device_id my_i2c_id[] = { { "bmp280", 0 }, { }, };

static struct i2c_driver my_i2c_driver = { .driver =
		{ .name = "my_i2c_driver", }, .probe = myprobe, .id_table = my_i2c_id,
		.remove = myremove, };

static int __init foo_init(void)
{
	pr_info("init my_i2c_driver\n");
return i2c_add_driver(&my_i2c_driver);
}

static void __exit foo_cleanup(void)
{
	i2c_del_driver(&my_i2c_driver);
}

module_init(foo_init);
module_exit(foo_cleanup);

MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Andy");
MODULE_DESCRIPTION("andy one-key driver");
MODULE_ALIAS("one-key");
